/**
 * Copyright © 2013 Creativor Studio.
 * About license information, please see LICENSE.txt.
 */
package org.creativor.rayson.serialize;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;

/**
 * @author creativor
 * 
 */
class Serializer {

	private static final int BUFFER_SIZE = 512;
	private final Object obj;
	private final DataOutputStream dos;
	private final ByteArrayOutputStream buffer;
	private final SerializableType thisType;

	/**
	 * @param obj
	 * @throws UnsupportedTypeException
	 */
	Serializer(final Object obj) throws UnsupportedTypeException {
		this.obj = obj;
		thisType = Types.typeOf(obj);
		this.buffer = new ByteArrayOutputStream(BUFFER_SIZE);
		this.dos = new DataOutputStream(buffer);
	}

	/**
	 * @return
	 * @throws UnsupportedTypeException
	 * @throws IOException
	 */
	public byte[] serialize() throws UnsupportedTypeException {

		try {
			writeHeader();
			writeThisObject();
			writeFields();
		} catch (final IOException e) {
			// Impossible, ignore it.
		} finally {
			try {
				dos.close();
			} catch (final Exception e) {
				// Impossible, ignore it.
			}
		}

		return buffer.toByteArray();
	}

	private void writeFields() throws IOException {
		this.thisType.writeFields(dos, this.obj);
	}

	private void writeHeader() throws IOException {
		this.dos.writeShort(Constants.MAGIC_NUMBER);
		this.dos.writeByte(Constants.VERSION);
	}

	private void writeThisObject() throws IOException, UnsupportedTypeException {
		this.dos.writeByte(thisType.getType());
		this.thisType.write(this.dos, this.obj);
	}
}